#version 410

in vec2 fs_SSVelocity;
in vec3 fs_Normal;

uniform uint u_objectID;
uniform uint u_Flags;
uniform float u_frameTime;

out vec4 out_Misc;
out vec4 out_Diffuse;
out vec4 out_Normal;
out vec4 out_Depth;

// Vertex/Texture coloring
#ifdef VERT_COLOR
in vec3 fs_Color;
#else
in vec2 fs_txCoord;
uniform sampler2D u_Texture;
#endif

// From http://aras-p.info/texts/CompactNormalStorage.html
vec2 encodeNormal(in vec3 normal) {
	float f = sqrt(8.0f*normal.z + 8.0f);
	return normal.xy / f + .5f;
}

// Code from : http://aras-p.info/texts/CompactNormalStorage.html
vec3 unpackNormal(vec2 encNorm) {
	vec2 fenc = encNorm*4.0f - 2.0f;
	float f = dot(fenc, fenc);
	float g = sqrt(1.0f -.25f*f);
	return vec3(fenc*g,1.0f - .5f*f);
}

vec4 packFloatTo4x8(in float val) {
	uint a = floatBitsToInt(val);
	return vec4((bitfieldExtract(a,0,8))/256.0f,
				(bitfieldExtract(a,8,8))/256.0f,
				(bitfieldExtract(a,16,8))/256.0f,
				(bitfieldExtract(a,24,8))/256.0f);
}

float unpack4x8ToFloat(in vec4 val) {
	uint a = uint(val.x*256.0f+.5f) + 
	uint(val.y*256.0f+.5f)*256u + 
	uint(val.z*256.0f+.5f)*256u*256u+
	uint(val.w*256.0f+.5f)*256u*256u*256u;
	return uintBitsToFloat(a);
}

// Packing and unpacking code courtesy of:
// http://www.ozone3d.net/blogs/lab/20080604/glsl-float-to-rgba8-encoder/
// http://olivers.posterous.com/linear-depth-in-glsl-for-real
vec4 pack2FloatTo4x8(in vec2 val) {
	const vec2 bitSh = vec2(256.0f, 1.0f);
	const vec2 bitMsk = vec2(0.0f, 1.0f/256.0f);
	vec2 res1 = fract(val.x * bitSh);
	//res1 -= res1.xx * bitMsk;
	vec2 res2 = fract(val.y * bitSh);
	//res2 -= res2.xx * bitMsk;
	
	return vec4(res1.x,res1.y,res2.x,res2.y);
}

vec2 unpack4x8To2Float(in vec4 val) {
	const vec2 unshift = vec2(1.0f/256.0f, 1.0f);
	return vec2(dot(val.xy, unshift), dot(val.zw, unshift));
}

/*
vec4 pack2FloatTo4x8(in vec2 val) {
	uint a = packUnorm2x16(val);
	return vec4((bitfieldExtract(a,0,8))/256.0f,
				(bitfieldExtract(a,8,8))/256.0f,
				(bitfieldExtract(a,16,8))/256.0f,
				(bitfieldExtract(a,24,8))/256.0f);
}

vec2 unpack4x8To2Float(in vec4 val) {
	uint a = uint(val.x*256.0f+.5f) + 
	uint(val.y*256.0f+.5f)*256u + 
	uint(val.z*256.0f+.5f)*256u*256u+
	uint(val.w*256.0f+.5f)*256u*256u*256u;
	return unpackUnorm2x16(a);
}
*/

void main(void) {
	// Divide ssVelocity by frame time, scale between 0-1
	// It should automatically clip b/w 0 and 1
	vec2 ssVel = .04f*sign(fs_SSVelocity)*sqrt(abs(fs_SSVelocity)) + .5f;
	if(u_Flags < 2)
		ssVel = vec2(.0f,.0f);
	out_Misc = vec4(ssVel, u_objectID/256.0f, u_Flags/256.0f);
		
	out_Depth = packFloatTo4x8(gl_FragCoord.z);
	out_Normal = pack2FloatTo4x8(encodeNormal(normalize(fs_Normal)));
	
	uint diffuseInt;
	
#ifdef VERT_COLOR
	out_Diffuse = vec4(fs_Color.rgb, .0f);
#else
	out_Diffuse = vec4(texture(u_Texture, fs_txCoord).rgb, .0f);
#endif
}